/*!
 * \file cq_city_payment_core.c
 *
 * \brief 共通定义
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * 共通使用的宏和结构体
 *
 * \version 1.0
 * \author jikw
 * \date 2017/3/21
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "config.h"
#include "frct_comm.h"
#include "frreport_comm.h"
#include "frservice_comm.h"
#include "frbyte_buffer.h"
#include "iconv2utf8.h"
#include "cq_city_payment_core.h"

extern void *g_p_apm_context;
extern pthread_spinlock_t g_spin_cq_list_lock;  //全局哈希表的自旋锁
extern Frhash_header *p_cq_city_payment_list;   //哈希表头存cq_city_payment_data
struct timeval g_st_time;

typedef struct __st_cq_city_payment_data
{
    L4_transaction st_l4_trans;                 //L4信息统计
    Frlist_header *p_report_comm;               //用于临时存储report的公共部分数据
    Frlist_header *p_report_req;                //用于临时存储report的请求部分数据
} cq_city_payment_data;

typedef struct __st_L7session_cq_city_payment_private
{
    unsigned long ul_seq;                       //序列号，1次req和response时，使用同一个序列号
    L4_transaction st_l4_trans;                 //数据
    Frreport_body_data *p_st_body_data_req;
    Frreport_body_data *p_st_body_data_resp;
    Frbyte_Packet *p_req_packet;                //存请求bytebuff数据
    Frbyte_Packet *p_resp_packet;               //存相应bytebuff数据
} L7session_cq_city_payment_private;

typedef struct __st_cq_city_payment_map
{
    unsigned int ui_code;
    char arr_name[128];
} cq_city_payment_map;

cq_city_payment_map arr_cq_city_payment_cmp_maps[] = {
    {1, "实时贷记"},
    {2, "实时借记"},
    {3, "贷记退汇"},
    {6, "借记冲正"},
    {9, "支付业务回执"},
    {101, "账户信息查询请求"},
    {102, "账户信息查询回执"},
    {201, "查询"},
    {202, "查复"},
    {205, "账户信息变更"},
    {207, "交易明细查询"},
    {208, "交易明细查询回执"},
    {209, "自由格式信息"},
    {305, "账户信息变更返回"},
    {418, "系统状态变更"},
    {501, "登陆"},
    {502, "登陆返回"},
    {503, "退出申请"},
    {504, "退出申请返回"},
    {505, "强制退出"},
    {613, "明细下载申请"},
    {614, "明细对账"},
    {642, "行号信息变更"},
    {702, "日切通知"},
    {704, "场次变更通知"},
    {706, "银行资金清算"},
    {713, "汇总对账"},
    {714, "汇总对账返回"},
    {751, "通讯检查"},
    {752, "通讯检查返回"},
    {999, "通用返回"}
};

/*!
 * cq_city_payment私有数据创建
 *
 * \param void
 *
 * \return NULL          内存分配失败\n
 *         p_st_private  内存分配成功
 *
 * \note
 *
 */
FR_STATIC L7session_cq_city_payment_private* __cq_city_payment_private_create(void)
{
    L7session_cq_city_payment_private *p_st_private = NULL;
    p_st_private = (L7session_cq_city_payment_private*)frmalloc(sizeof(L7session_cq_city_payment_private));
    if (p_st_private == NULL)
        return NULL;
    memset(p_st_private, 0x00, sizeof(L7session_cq_city_payment_private));

    return p_st_private;
}

/*!
 * 私有信息重置
 *
 * \param p_private_session  (cq_city_payment的私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
FR_STATIC int __cq_city_payment_session_reset(void *p_private_session)
{
    L7session_cq_city_payment_private *p_st_private = (L7session_cq_city_payment_private*)p_private_session;

    if (p_st_private)
    {
        if (p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if (p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if (p_st_private->p_req_packet)
            bytebuff_free(&(p_st_private->p_req_packet));

        if (p_st_private->p_resp_packet)
            bytebuff_free(&(p_st_private->p_resp_packet));
    }
    return FR_SUCC;
}

/*!
 * 判断是否是cq_city_payment协议
 *
 * \param p_st_conn      (输入数据信息)
 * \param p_st_packet    (输入数据)
 *
 * \return APM_L7_IS_YES  属于cq_city_payment协议\n
 *         APM_L7_IS_NO   不属于cq_city_payment协议
 *
 * \note
 *
 */
int cq_city_payment_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
//    int i_ret = 0;

    //报文包括报文头、报文体、报文尾三部分。
    //报文头定长138、报文尾定长36，报文体为带TAG的可变长度部分。

    if (p_st_packet == NULL ||
        p_st_packet->p_payload == NULL ||
        p_st_packet->ui_payload_len < 138+36 ||
        p_st_conn == NULL)
        return APM_L7_IS_NO;

    //块标识
    if (memcmp(p_st_packet->p_payload, BLOCKMARK, 3) != 0)
        return APM_L7_IS_NO;
    //版本识别码
//    if (*(p_st_packet->p_payload+3) != VERID)
//        return APM_L7_IS_NO;
    //业务交易码:子系统识别1位、CMP号码3位、位置1位为空、序号3位为空
    if (*(p_st_packet->p_payload+10) != IDENTIFICATION_S &&
        *(p_st_packet->p_payload+10) != IDENTIFICATION_B &&
        *(p_st_packet->p_payload+10) != IDENTIFICATION_W)
        return APM_L7_IS_NO;
    if (*(p_st_packet->p_payload+14) != '\x20')
        return APM_L7_IS_NO;
    if (memcmp(p_st_packet->p_payload+15, "\x20\x20\x20", 3) != 0)
        return APM_L7_IS_NO;
    //报文用途
    if (*(p_st_packet->p_payload+42) != '\x20')
        return APM_L7_IS_NO;
    //输出识别
    if (*(p_st_packet->p_payload+43) != '\x20')
        return APM_L7_IS_NO;
    //有效时间
//    if (memcmp(p_st_packet->p_payload+106, EXPTIME, 4) != 0)
//        return APM_L7_IS_NO;
    //提交时间
//    if (memcmp(p_st_packet->p_payload+110, DELITIME, 6) != 0)
//        return APM_L7_IS_NO;
    //信息优先级
    if (*(p_st_packet->p_payload+116) != MESGPRI_5 &&
        *(p_st_packet->p_payload+116) != MESGPRI_9)
        return APM_L7_IS_NO;
    //预留
    if (memcmp(p_st_packet->p_payload+117, RESERVE, 20) != 0)
        return APM_L7_IS_NO;
    //结束标识（报文头）
    if (*(p_st_packet->p_payload+137) != FINALMARK)
        return APM_L7_IS_NO;

//    i_ret = frct_get_direct_known(p_st_conn);
//    if (i_ret == FR_DIRECT_UNKNOWN)
//        frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
//    frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);

    return APM_L7_IS_YES;
}

/*!
 * 链表节点释放规则
 *
 * \Frlist_node *p_st_node
 *
 * \return void
 *
 * \note
 *
 */
void cq_city_payment_list_node_free(Frlist_node *p_st_node)
{
    cq_city_payment_data *p_st_info = NULL;

    if (p_st_node==NULL || p_st_node->data == NULL )
        return;

    p_st_info = (cq_city_payment_data *)FRLIST_GET_NODE_DATA(p_st_node);

    if (p_st_info->p_report_req)
        frreport_body_l7list_free(&p_st_info->p_report_req);
    if (p_st_info->p_report_comm)
        frreport_body_l7list_free(&p_st_info->p_report_comm);

    frfree(p_st_info);
    return;
}

/*!
 * 用二分法查找arr_cq_city_payment_cmp_maps匹配的序号
 *
 * \param i_key           (返回码)
 *
 * \return -1              未找到\n
 *         index           找到的下标
 *
 * \note
 *
 */
FR_STATIC int __get_cmp(unsigned int i_key)
{
    int i_len = 0;
    int i_mid = 0;
    int i_front = 0;
    int i_back = 0;

    i_len = sizeof(arr_cq_city_payment_cmp_maps) / sizeof(arr_cq_city_payment_cmp_maps[0]);
    i_back = i_len - 1;

    while (i_front <= i_back)
    {
        i_mid = (i_front + i_back) / 2;
        if (arr_cq_city_payment_cmp_maps[i_mid].ui_code == i_key)
            return i_mid;
        if (arr_cq_city_payment_cmp_maps[i_mid].ui_code < i_key)
            i_front = i_mid + 1;
        else
            i_back = i_mid - 1;
    }

    return -1;
}

/*!
 * 报文头解析
 *
 * \param p_packet        (req数据)
 * \param p_st_body_data
 * \param pp_data_out     取出的mesgID
 *
 * \return FR_SUCC   成功\n
 *         FR_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __bashead_parse(Frbyte_Packet *p_packet
                        , Frreport_body_data *p_st_body_data
                        , char ***ppp_data_out
                        , int i_req_flag)
{
    int i_cmp_map_index = 0;
    uint8_t u8_value = 0;
    char arr_temp[16];
    char arr_mesgid[32];
    char arr_mesgreqno[32];
    char arr_name[64];
    const char *p_name = NULL;

    if (p_packet == NULL || p_st_body_data == NULL)
        return FR_FAIL;

    memset(arr_temp, 0x00, sizeof(arr_temp));
    memset(arr_mesgid, 0x00, sizeof(arr_mesgid));
    memset(arr_mesgreqno, 0x00, sizeof(arr_mesgreqno));
    memset(arr_name, 0x00, sizeof(arr_name));

    if (i_req_flag == 1)
        p_name = "request.cq_city_payment";
    else
        p_name = "response.cq_city_payment";

    //解析报文头取有价值信息：子系统识别、CMP号码、源地址、目的地址、工作日期、发送时间、信息优先级
    //跳过块标识3位{1：版本识别码1位为0 报文长度6位
    if (bytebuff_skip(p_packet, 10) != FR_SUCC)
        return FR_FAIL;
    //取业务交易码：子系统识别1位、CMP号码3位、位置1位为空、序号3位为空
    snprintf(arr_name, sizeof(arr_name), "%s.%s", p_name, "subsystem");
    if (bytebuff_get_char(p_packet, &u8_value) == FR_FAIL)
        return FR_FAIL;
    if (u8_value == IDENTIFICATION_S)
    {
        if (frreport_body_l7_add_str(p_st_body_data, arr_name, "业务处理中心后台子系统") == FR_FAIL)
            return FR_FAIL;
    }
    else if (u8_value == IDENTIFICATION_B)
    {
        if (frreport_body_l7_add_str(p_st_body_data, arr_name, "商业银行") == FR_FAIL)
            return FR_FAIL;
    }
    else if (u8_value == IDENTIFICATION_W)
    {
        if (frreport_body_l7_add_str(p_st_body_data, arr_name, "WEB子系统") == FR_FAIL)
            return FR_FAIL;
    }
    else
        return FR_FAIL;
    //3位cmp码设为TRANS_CODE 翻译后设为TRANS_TITLE
    if (bytebuff_get_bytes(p_packet, arr_temp, 3) == FR_FAIL)
        return FR_FAIL;
    if (i_req_flag == 1)
    {
        if (frreport_body_l7_add_str(p_st_body_data, "transaction.type_code", arr_temp) == FR_FAIL)
            return FR_FAIL;
    }
    else
    {
        if (frreport_body_l7_add_str(p_st_body_data, "response.cq_city_payment.cmpcode", arr_temp) == FR_FAIL)
            return FR_FAIL;
    }
    if ((i_cmp_map_index = __get_cmp((unsigned int) atoi(arr_temp))) == -1)
        return FR_FAIL;
    if (i_req_flag == 1)
    {
        if (frreport_body_l7_add_str(p_st_body_data,
            "transaction.type_name",
            arr_cq_city_payment_cmp_maps[i_cmp_map_index].arr_name) == FR_FAIL)
            return FR_FAIL;
        if (frreport_body_l7_add_str(p_st_body_data,
            APM_REPORT_KEY_TRANS_TITLE,
            arr_cq_city_payment_cmp_maps[i_cmp_map_index].arr_name) == FR_FAIL)
            return FR_FAIL;
    }
    else
    {
        if (frreport_body_l7_add_str(p_st_body_data,
            "response.cq_city_payment.cmp",
            arr_cq_city_payment_cmp_maps[i_cmp_map_index].arr_name) == FR_FAIL)
            return FR_FAIL;
    }
    //跳过位置、序号
    if (bytebuff_skip(p_packet, 4) != FR_SUCC)
        return FR_FAIL;
    //取源地址
    snprintf(arr_name, sizeof(arr_name), "%s.%s", p_name, "startaddr");
    if (bytebuff_get_bytes(p_packet, arr_temp, 12) == FR_FAIL)
        return FR_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, arr_name, arr_temp) == FR_FAIL)
        return FR_FAIL;
    //取目的地址
    snprintf(arr_name, sizeof(arr_name), "%s.%s", p_name, "destaddr");
    if (bytebuff_get_bytes(p_packet, arr_temp, 12) == FR_FAIL)
        return FR_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, arr_name, arr_temp) == FR_FAIL)
        return FR_FAIL;
    //跳过报文用途1位 报文识别1位
    if (bytebuff_skip(p_packet, 2) != FR_SUCC)
        return FR_FAIL;
    //报文标识符20位
    snprintf(arr_name, sizeof(arr_name), "%s.%s", p_name, "mesgID");
    if (bytebuff_get_bytes(p_packet, arr_mesgid, 20) == FR_FAIL)
        return FR_FAIL;
    if (i_req_flag == 1)
    {
        if (frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_CODE, arr_mesgid) == FR_FAIL)
            return FR_FAIL;
    }
    else
    {
        if (frreport_body_l7_add_str(p_st_body_data, arr_name, arr_mesgid) == FR_FAIL)
            return FR_FAIL;
    }
    if (i_req_flag == 1)
        **ppp_data_out = frstrdup(arr_mesgid);
    //报文参考号20位
    snprintf(arr_name, sizeof(arr_name), "%s.%s", p_name, "mesgReqNo");
    if (bytebuff_get_bytes(p_packet, arr_mesgreqno, 20) == FR_FAIL)
        return FR_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, arr_name, arr_mesgreqno) == FR_FAIL)
        return FR_FAIL;
    if (i_req_flag == 0)
        **ppp_data_out = frstrdup(arr_mesgreqno);
    //取工作日期
    snprintf(arr_name, sizeof(arr_name), "%s.%s", p_name, "workdate");
    if (bytebuff_get_bytes(p_packet, arr_temp, 8) == FR_FAIL)
        return FR_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, arr_name, arr_temp) == FR_FAIL)
        return FR_FAIL;
    //取发送时间
    snprintf(arr_name, sizeof(arr_name), "%s.%s", p_name, "senttime");
    if (bytebuff_get_bytes(p_packet, arr_temp, 14) == FR_FAIL)
        return FR_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, arr_name, arr_temp) == FR_FAIL)
        return FR_FAIL;
    //跳过有效时间4位为空 提交时间6位为空
    if (bytebuff_skip(p_packet, 10) != FR_SUCC)
        return FR_FAIL;
    //信息优先级
    snprintf(arr_name, sizeof(arr_name), "%s.%s", p_name, "mesgpri");
    if (bytebuff_get_char(p_packet, &u8_value) == FR_FAIL)
        return FR_FAIL;
    if (u8_value == MESGPRI_5)
    {
        if (frreport_body_l7_add_str(p_st_body_data, arr_name, "加急") == FR_FAIL)
            return FR_FAIL;
    }
    else if (u8_value == MESGPRI_9)
    {
        if (frreport_body_l7_add_str(p_st_body_data, arr_name, "普通") == FR_FAIL)
            return FR_FAIL;
    }
    else
        return FR_FAIL;
    //跳过预留20位为空 结束标识1位为}
    if (bytebuff_skip(p_packet, 21) != FR_SUCC)
        return FR_FAIL;

    return FR_SUCC;
}

/*!
 * 报文正文解析
 *
 * \param p_packet        (req数据)
 * \param p_st_body_data
 * \param i_req_flag      (req标志位)
 *
 * \return FR_SUCC   成功\n
 *         FR_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __text_parse(Frbyte_Packet *p_packet
                        , Frreport_body_data *p_st_body_data
                        , int i_req_flag)
{
    int i_flag = 0;
    int i_len = 0;
    int i_index = 0;
    int i_text_end = 0;
    unsigned int i_buff_out_len = 0;
    uint8_t u8_value = 0;
    const char *p_name = NULL;
    char *p_value = NULL;
    char *p_buff_out = NULL;
    char arr_text_start_mask[4];
    char arr_tag_name[4];
    char arr_name[64];

    if (p_packet == NULL || p_st_body_data == NULL)
        return FR_FAIL;

    memset(arr_text_start_mask, 0x00, sizeof(arr_text_start_mask));
    memset(arr_tag_name, 0x00, sizeof(arr_tag_name));
    memset(arr_name, 0x00, sizeof(arr_name));

    if (i_req_flag == 1)
        p_name = "request.cq_city_payment.tag";
    else
        p_name = "response.cq_city_payment.tag";

    //解析报文正文取有价值信息：TAG名称和TAG值、文件路径
    if (bytebuff_get_bytes(p_packet, arr_text_start_mask, 3) == FR_FAIL)
        return FR_FAIL;
    if (memcmp(arr_text_start_mask, SHORTTESTMASK, 3) == 0)
    {
        //短报文正文
        while(1)
        {
            //遇到结束标识跳出循环
            if (bytebuff_peek_char(p_packet, &u8_value) == FR_FAIL)
                return FR_FAIL;
            if (u8_value == FINALMARK)
                break;
            //1位tag分隔符
            if (bytebuff_get_char(p_packet, &u8_value) == FR_FAIL)
                return FR_FAIL;
            if (u8_value != TAGBREAK)
                return FR_FAIL;
            //3位tag名字
            if (bytebuff_get_bytes(p_packet, arr_tag_name, 3) == FR_FAIL)
                return FR_FAIL;
            //TAG内容需要GBK解码
            snprintf(arr_name, sizeof(arr_name), "%s.%s", p_name, arr_tag_name);
            if (memcmp(arr_tag_name, TAG_50A, 3) == 0 ||
                memcmp(arr_tag_name, TAG_59A, 3) == 0 ||
                memcmp(arr_tag_name, TAG_72A, 3) == 0 ||
                memcmp(arr_tag_name, TAG_CR2, 3) == 0 ||
                memcmp(arr_tag_name, TAG_OPE, 3) == 0 ||
                memcmp(arr_tag_name, TAG_OPR, 3) == 0 ||
                memcmp(arr_tag_name, TAG_RNM, 3) == 0 ||
                memcmp(arr_tag_name, TAG_BNM, 3) == 0 ||
                memcmp(arr_tag_name, TAG_MSG, 3) == 0 ||
                memcmp(arr_tag_name, TAG_DTM, 3) == 0 ||
                memcmp(arr_tag_name, TAG_BNN, 3) == 0 ||
                memcmp(arr_tag_name, TAG_ADD, 3) == 0 ||
                memcmp(arr_tag_name, TAG_LKN, 3) == 0 ||
                memcmp(arr_tag_name, TAG_LTN, 3) == 0)
                i_flag = 1;

            //1位tag分隔符
            if (bytebuff_get_char(p_packet, &u8_value) == FR_FAIL)
                return FR_FAIL;
            if (u8_value != TAGBREAK)
                return FR_FAIL;
            //不定长tag内容 此位置向后搜索tag分隔符判断位置在结束标识之前之后
            if (bytebuff_memstr(p_packet, bytebuff_getPosition(p_packet), 0, "}", 1, &i_text_end) == FR_FAIL)
                return FR_FAIL;
            if (bytebuff_memstr(p_packet, bytebuff_getPosition(p_packet), 0, ":", 1, &i_index) == FR_FAIL)
                return FR_FAIL;
            //循环取TAG
            if (i_index < i_text_end)
            {
                i_len = i_index - bytebuff_getPosition(p_packet);
                if (i_len == 0)
                {
                    if (frreport_body_l7_add_str(p_st_body_data, arr_name, "") == FR_FAIL)
                        return FR_FAIL;
                }
                else
                {
                    p_value = (char*)frmalloc(i_len+1);
                    if (p_value == NULL)
                        return FR_FAIL;
                    memset(p_value, 0x00, i_len+1);
                    if (bytebuff_get_bytes(p_packet, p_value, i_len) == FR_FAIL)
                        goto ERROR;
                    if (i_flag == 1)
                    {
                        if (iconv_to_utf8(p_value, i_len+1, "GBK", &p_buff_out, &i_buff_out_len) == FR_FAIL)
                            goto ERROR;
                        if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_buff_out) == FR_FAIL)
                            goto ERROR;
                        i_flag = 0;
                        frfree(p_value);
                        p_value = NULL;
                        frfree(p_buff_out);
                        p_buff_out = NULL;
                    }
                    else
                    {
                        if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_value) == FR_FAIL)
                            goto ERROR;
                        frfree(p_value);
                        p_value = NULL;
                    }
                }
            }
            //最后一个TAG
            else
            {
                i_len = i_text_end - bytebuff_getPosition(p_packet);
                if (i_len == 0)
                {
                    if (frreport_body_l7_add_str(p_st_body_data, arr_name, "") == FR_FAIL)
                        return FR_FAIL;
                }
                else
                {
                    p_value = (char*)frmalloc(i_len+1);
                    if (p_value == NULL)
                        return FR_FAIL;
                    memset(p_value, 0x00, i_len+1);
                    if (bytebuff_get_bytes(p_packet, p_value, i_len) == FR_FAIL)
                        goto ERROR;
                    if (i_flag == 1)
                    {
                        if (iconv_to_utf8(p_value, i_len+1, "GBK", &p_buff_out, &i_buff_out_len) == FR_FAIL)
                            goto ERROR;
                        if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_buff_out) == FR_FAIL)
                            goto ERROR;
                        i_flag = 0;
                        frfree(p_value);
                        p_value = NULL;
                        frfree(p_buff_out);
                        p_buff_out = NULL;
                    }
                    else
                    {
                        if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_value) == FR_FAIL)
                            goto ERROR;
                        frfree(p_value);
                        p_value = NULL;
                    }
                }
            }
        }
    }
    else if (memcmp(arr_text_start_mask, LONGTESTMASK, 3) == 0)
    {
        //长报文正文
        if (bytebuff_memstr(p_packet, bytebuff_getPosition(p_packet), 0, "}", 1, &i_text_end) == FR_FAIL)
            return FR_FAIL;
        i_len = i_text_end - bytebuff_getPosition(p_packet);
        p_value = (char*)frmalloc(i_len+1);
        if (p_value == NULL)
            return FR_FAIL;
        memset(p_value, 0x00, i_len+1);
        if (bytebuff_get_bytes(p_packet, p_value, i_len) == FR_FAIL)
            goto ERROR;
        if (frreport_body_l7_add_str(p_st_body_data, p_name, p_value) == FR_FAIL)
            goto ERROR;
        frfree(p_value);
    }
    else
        return FR_FAIL;

    return FR_SUCC;

ERROR:
    if (p_value)
        frfree(p_value);
    if (p_buff_out)
        frfree(p_buff_out);
    return FR_FAIL;
}

/*!
 * req数据解析
 *
 * \param p_packet        (req数据)
 * \param p_st_body_data
 * \param p_mesgid        (取出的mesgid)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __req_parse(Frbyte_Packet *p_packet
                        , Frreport_body_data *p_st_body_data
                        , char **pp_mesgid)
{
    if (p_packet == NULL || p_st_body_data == NULL)
        return APM_L7_ANALYZE_FAIL;

    //解析报文头
    if (__bashead_parse(p_packet, p_st_body_data, &pp_mesgid, 1) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //解析报文正文
    if (__text_parse(p_packet, p_st_body_data, 1) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //解析报文尾：无有价值信息无需解析

    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
}

/*!
 * resp数据解析
 *
 * \param p_packet        (resp数据)
 * \param p_st_body_data
 * \param p_mesgreqno     (mesgreqno)
 *
 * \return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC)   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __resp_parse(Frbyte_Packet *p_packet
                         , Frreport_body_data *p_st_body_data
                         , char **pp_mesgreqno)
{
    if (p_packet == NULL || p_st_body_data == NULL)
        return APM_L7_ANALYZE_FAIL;

    //解析报文头
    if (__bashead_parse(p_packet, p_st_body_data, &pp_mesgreqno, 0) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //解析报文正文
    if (__text_parse(p_packet, p_st_body_data, 0) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //解析报文尾：无有价值信息无需解析

    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);
}

/*!
 * req的p_report_comm、p_report_req、L4信息和ID存进链表
 *
 * \param p_st_private    (cq_city_payment私有数据)
 * \param p_mesgid        (mesgID)
 *
 * \return FR_FAIL        失败\n
 *         FR_SUCC        成功
 *
 * \note
 *
 */
FR_STATIC int __cq_city_payment_add_req_list(L7session_cq_city_payment_private *p_st_private, char *p_mesgid)
{
    cq_city_payment_data *p_st_report = NULL;
	Frlist_node *p_st_node = NULL;
	Frlist_node *p_st_gotnode = NULL;
	L4_transaction *p_st_l4_trans = NULL;

    if (p_st_private == NULL)
        return FR_FAIL;

//    //创建链表
//    if (p_cq_city_payment_list == NULL)
//    {
//        pthread_spin_lock(&g_spin_cq_list_lock);
//        p_cq_city_payment_list = frhash2_create2(100);
//        pthread_spin_unlock(&g_spin_cq_list_lock);
//    }

    p_st_l4_trans = &(p_st_private->st_l4_trans);

    //req的p_report_comm、p_report_req、L4信息和ID存进链表
    p_st_report = (cq_city_payment_data *)frmalloc(sizeof(cq_city_payment_data));
    memset(p_st_report, 0x00, sizeof(cq_city_payment_data));

    //拷贝L4信息统计
    memcpy(&p_st_report->st_l4_trans, p_st_l4_trans, sizeof(L4_transaction));
    //拷贝相关链表
    p_st_report->p_report_comm = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_private->p_st_body_data_req);
    if (p_st_report->p_report_comm == NULL)
        goto ERROR;
    p_st_report->p_report_req = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_private->p_st_body_data_req);
    if (p_st_report->p_report_req == NULL)
        goto ERROR;

    p_st_node = frlist_node_create(p_st_report);
    //存list之前 判断key值(mesgID)是否存在 如存在删除节点 再加节点
    pthread_spin_lock(&g_spin_cq_list_lock);
    p_st_gotnode = frhash2_getStr(p_cq_city_payment_list, p_mesgid, 20);
    if (p_st_gotnode != NULL)
    {
        frhash2_del(p_cq_city_payment_list, p_st_gotnode, cq_city_payment_list_node_free);
        p_st_gotnode = NULL;
    }
    frhash2_addStr(p_cq_city_payment_list, p_mesgid, 20, p_st_node);
    pthread_spin_unlock(&g_spin_cq_list_lock);

    return FR_SUCC;

ERROR:
    if (p_st_report)
        frfree(p_st_report);
    if (p_st_report->p_report_comm)
        frreport_body_l7list_free(&p_st_report->p_report_comm);
    if (p_st_report->p_report_req)
        frreport_body_l7list_free(&p_st_report->p_report_req);
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * 检查是否超时
 *
 * \param p_node
 * \param p_data
 *
 * \return int
 *
 * \note
 *
 */
FR_STATIC int __check_timeout(Frlist_node* p_node, const void *p_data)
{
    cq_city_payment_data *p_st_info = NULL;
    Frhash_header *p_header = (Frhash_header *)p_data;

    p_st_info = (cq_city_payment_data *)p_node->data;

    if (p_st_info->st_l4_trans.st_request_time.tv_sec + CQ_TIMEOUT <= g_st_time.tv_sec)
    {
        frhash2_del(p_header, p_node, cq_city_payment_list_node_free);
        return 1;
    }

    return 1;
}

/*!
 * 清除hash中超时的node
 *
 * \param p_hash_stmt
 * \param st_timestamp
 *
 * \return int
 *
 * \note
 *
 */
FR_STATIC void __clear_timeout_node(Frhash_header *p_header, struct timeval st_timestamp)
{
    g_st_time = st_timestamp;
    frhash2_run(p_header, p_header, __check_timeout);

    return;
}

/*!
 * cq_city_payment的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *         APM_L7_ANALYZE_TODO
 *
 * \note
 *
 */
FR_STATIC int __req_data_analysis(Conntrack *p_st_conn
                                , Apm_packet *p_st_packet
                                , Frhash_header *p_st_hash_report
                                , L7_session *p_st_session)
{
    int i_ret = 0;
    unsigned long ul_tmp = 0;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data *p_st_report_data = NULL;
    L7session_cq_city_payment_private *p_st_private = NULL;
    char *p_mesgid = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_cq_city_payment_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    //创建数据链表
    if (p_st_private->p_st_body_data_req == NULL)
    {
        p_st_private->p_st_body_data_req = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_body_data_req == NULL)
            goto ERROR;

        if (frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_req, p_st_conn) == FR_FAIL)
            goto ERROR;

        //seq ++
        p_st_private->ul_seq = frct_seq_increase(p_st_conn);

        if (p_st_l4_trans->st_request_time_first_byte.tv_sec==0 && p_st_l4_trans->st_request_time_first_byte.tv_usec==0)
        {
            //st_request_time_first_byte
            p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        //创建bytebuff
        if (p_st_private->p_req_packet == NULL)
        {
            p_st_private->p_req_packet = bytebuff_creat();
            if (p_st_private->p_req_packet == NULL)
                goto ERROR;
        }
    }
    //请求的字节数
    p_st_l4_trans->l_request_bytes += p_st_packet->ui_payload_len;

    if (p_st_private->p_req_packet == NULL)
        goto ERROR;

    //把这个包的数据先全加进bytebuff里
    if (bytebuff_add(p_st_private->p_req_packet, p_st_packet->p_payload, p_st_packet->ui_payload_len) != FR_SUCC)
        goto ERROR;

    //req解析
    i_ret = __req_parse(p_st_private->p_req_packet, p_st_private->p_st_body_data_req, &p_mesgid);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto ERROR;

    if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ID, p_st_private->ul_seq) == FR_FAIL)
        goto ERROR;

    //start time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_START_TIMESTAMP, &p_st_l4_trans->st_request_time_first_byte) == FR_FAIL)
        goto ERROR;

    //st_request_time
    p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    ul_tmp = frtime_diff(&(p_st_l4_trans->st_request_time_first_byte), &(p_st_l4_trans->st_request_time));
    //send_time_us
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //request bytes
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_DATA_BYTES, p_st_l4_trans->l_request_bytes) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_l4_trans->st_request_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);
    if (p_st_report_data == NULL)
        goto ERROR;

    if (__cq_city_payment_add_req_list(p_st_private, p_mesgid) == FR_FAIL)
        goto ERROR;

    pthread_spin_lock(&g_spin_cq_list_lock);
    __clear_timeout_node(p_cq_city_payment_list, p_st_packet->st_timestamp);
    pthread_spin_unlock(&g_spin_cq_list_lock);

    if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_req) == FR_FAIL)
        goto ERROR;
    p_st_private->p_st_body_data_req = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    __cq_city_payment_session_reset((void *)(p_st_private));

    if (p_mesgid)
        frfree(p_mesgid);

    return i_ret;

ERROR:
    if (p_mesgid)
        frfree(p_mesgid);
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    __cq_city_payment_session_reset((void *)(p_st_private));
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * cq_city_payment的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *         APM_L7_ANALYZE_TODO
 *
 * \note
 *
 */
FR_STATIC int __resp_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
    int i_ret = 0;
    unsigned long ul_tmp = 0;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data* p_st_report_data = NULL;
    L7session_cq_city_payment_private *p_st_private = NULL;
    char *p_mesgreqno = NULL;
    Frlist_node *p_st_node = NULL;
    cq_city_payment_data *p_st_data = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_cq_city_payment_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    if (p_st_private->p_st_body_data_resp == NULL)
    {
        //创建数据链表
        p_st_private->p_st_body_data_resp = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_body_data_resp == NULL)
            goto ERROR;

        if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0 && p_st_l4_trans->st_response_time_first_byte.tv_usec == 0)
        {
            p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        //创建bytebuff
        if (p_st_private->p_resp_packet == NULL)
        {
            p_st_private->p_resp_packet = bytebuff_creat();
            if (p_st_private->p_resp_packet == NULL)
                goto ERROR;
        }
    }

    //请求的字节数
    p_st_l4_trans->l_response_bytes += p_st_packet->ui_payload_len;

    if (p_st_private->p_resp_packet == NULL)
        goto ERROR;

    if (bytebuff_add(p_st_private->p_resp_packet, p_st_packet->p_payload, p_st_packet->ui_payload_len) != FR_SUCC)
        goto ERROR;

    //resp解析
    i_ret = __resp_parse(p_st_private->p_resp_packet, p_st_private->p_st_body_data_resp, &p_mesgreqno);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto ERROR;

    //取链表对应的request p_report_req p_report_comm
    pthread_spin_lock(&g_spin_cq_list_lock);
    p_st_node = frhash2_getStr(p_cq_city_payment_list, p_mesgreqno, 20);
    pthread_spin_unlock(&g_spin_cq_list_lock);
    if (p_st_node == NULL)
        goto ERROR;
    p_st_data = (cq_city_payment_data *)p_st_node->data;
    //数据上报
    FRREPORT_BODY_L7LIST_SET_REQ(p_st_private->p_st_body_data_resp, &p_st_data->p_report_req);
    FRREPORT_BODY_L7LIST_SET_COMM(p_st_private->p_st_body_data_resp, &p_st_data->p_report_comm);

    //server time
    ul_tmp = frtime_diff(&p_st_data->st_l4_trans.st_request_time, &(p_st_l4_trans->st_response_time_first_byte));
    pthread_spin_lock(&g_spin_cq_list_lock);
    frhash2_del(p_cq_city_payment_list, p_st_node, cq_city_payment_list_node_free);
    pthread_spin_unlock(&g_spin_cq_list_lock);
    if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //start time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_START_TIMESTAMP, &p_st_l4_trans->st_response_time_first_byte) == FR_FAIL)
        goto ERROR;

    //st_response_time
    p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DATA_BYTES, p_st_l4_trans->l_response_bytes) == FR_FAIL)
        goto ERROR;

    //down load time
    ul_tmp = frtime_diff(&(p_st_l4_trans->st_response_time_first_byte), &(p_st_l4_trans->st_response_time));
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_END_TIMESTAMP, &p_st_l4_trans->st_response_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);
    if (p_st_report_data == NULL)
        goto ERROR;

    if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_resp) == FR_FAIL)
        goto ERROR;
    p_st_private->p_st_body_data_resp = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    cq_city_payment_session_destroy(p_st_session->p_session_private);
    p_st_session->p_session_private = NULL;

    if (p_mesgreqno)
        frfree(p_mesgreqno);

    return i_ret;

ERROR:
    if (p_mesgreqno)
        frfree(p_mesgreqno);
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    __cq_city_payment_session_reset((void *)(p_st_private));
    frfree(p_st_private);
    p_st_session->p_session_private = NULL;
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * cq_city_payment的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
int cq_city_payment_analysis(Conntrack *p_st_conn
                           , Apm_packet *p_st_packet
                           , Frhash_header *p_st_hash_report)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_session *p_st_session = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    //到Conntrack中取得session信息
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    //fin、syn包销毁私有数据
    if (p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        cq_city_payment_session_destroy(p_st_session->p_session_private);
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

    //p_session_private分配内存
    if (p_st_session->p_session_private == NULL)
    {
        p_st_session->p_session_private = __cq_city_payment_private_create();
        //内存分配失败
        if (p_st_session->p_session_private == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    //只解析请求报文和响应报文 其确认收到消息不解析
    if (cq_city_payment_detect(p_st_conn, p_st_packet) == APM_L7_IS_NO)
        return APM_L7_ANALYZE_SUCC;
    //请求报文和响应报文设方向
    if (memcmp(p_st_packet->p_payload+64, RESERVE, 20) == 0)
    {
        p_st_packet->i_direction = FR_DIRECT_CLIENT2SRV;
        if (frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port) != FR_SUCC)
            return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        p_st_packet->i_direction = FR_DIRECT_SRV2CLIENT;
        if (frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port) != FR_SUCC)
            return APM_L7_ANALYZE_FAIL;
    }

    //request
    if (p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
    {
        i_ret = __req_data_analysis(p_st_conn, p_st_packet, p_st_hash_report, p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;
        return i_ret;
    }
    //response
    else
    {
        i_ret = __resp_data_analysis(p_st_conn, p_st_packet, p_st_hash_report, p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;
        return i_ret;
    }

ERROR:
    cq_city_payment_session_destroy(p_st_session->p_session_private);
    p_st_session->p_session_private = NULL;
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * 私有信息销毁
 *
 * \param p_private_session  (cq_city_payment的私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
int cq_city_payment_session_destroy(void *p_private_session)
{
    L7session_cq_city_payment_private *p_st_private = (L7session_cq_city_payment_private*)p_private_session;

    if (p_st_private)
    {
        if (p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if (p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if (p_st_private->p_req_packet)
            bytebuff_free(&(p_st_private->p_req_packet));

        if (p_st_private->p_resp_packet)
            bytebuff_free(&(p_st_private->p_resp_packet));

        frfree(p_st_private);
    }

    return FR_SUCC;
}
